<?php
    // $tu = new WZ_UnitTest;
    // $test = 3 + 7;
    // $res =  $tu->run($test, 10, 'Petit test');
    // echo $res;
    
    class WZ_UnitTest 
    {
        public $active			= true;
        public $results 		= array();
        public $strict			= false;
        public $_template 		= null;
        public $_template_rows	= null;	

        public function run($test, $expected = true, $testName = 'undefined')
        {
            if ($this->active == false) {
                return false;
            }
            
            $fonctions = array('is_string', 'is_bool', 'is_true', 'is_false', 'is_int', 'is_numeric', 'is_float', 'is_double', 'is_array', 'is_null');
        
            if (in_array($expected, $fonctions, true)) {
                $expected = str_replace('is_float', 'is_double', $expected);
                $result = ($expected($test)) ? true : false;	
                $extype = str_replace(array('true', 'false'), 'bool', str_replace('is_', '', $expected));
            } else {
                if ($this->strict == true) {
                    $result = ($test === $expected) ? true : false;	
                } else {
                    $result = ($test == $expected) ? true : false;	
                }
                $extype = gettype($expected);
            }
                    
            $back = $this->_backtrace();
        
            $report[] = array (
                'test_name'			=> $testName,
                'test_value'		=> self::dump($test),
                'test_datatype'		=> gettype($test),
                'res_value'		    => self::dump($expected),
                'res_datatype'		=> $extype,
                'result'			=> ($result === true) ? 'success' : 'failed',
                'file'				=> $back['file'],
                'line'				=> $back['line']
            );

            $this->results[] = $report;		
                    
            return($this->report($this->result($report)));
        }

        public function report($result = array())
        {
            if (count($result) == 0) {
                $result = $this->result();
            }

            $this->_parse_template();

            $r = '';
            foreach ($result as $res) {
                $table = '';
                foreach ($res as $key => $val) {
                    if ($key == 'ut_result') {
                        if ($val == 'ut_success') {
                            $val = '<span style="color: #0c0;">' . $val . '</span>';
                        } elseif ($val == 'ut_failed') {
                            $val = '<span style="color: #c00;">' . $val . '</span>';
                        }
                    }
                    $val = str_replace('ut_', '', $val);
                    $key = str_replace('ut_', '', $key);
                    $key = ucwords(str_replace('_', ' ', $key));
                    $temp = $this->_template_rows;
                    $temp = str_replace('{item}', $key, $temp);
                    $temp = str_replace('{result}', $val, $temp);
                    $table .= $temp;
                }

                $r .= str_replace('{rows}', $table, $this->_template);
            }
            return $r;
        }
        
        public function useStrict($state = true)
        {
            $this->strict = ($state === false) ? false : true;
        }
        
        public function active($state = true)
        {
            $this->active = ($state === false) ? false : true;
        }
        
        public function result($results = array())
        {	            
            if (count($results) == 0) {
                $results = $this->results;
            }
            $retval = array();
            foreach ($results as $result) {
                $temp = array();
                foreach ($result as $key => $val) {
                    if (is_array($val)) {
                        foreach ($val as $k => $v) {
                            if (false !== ($line = strtolower('ut_' . $v))) {
                                $v = $line;
                            }				
                            $temp['ut_' . $k] = $v;					
                        }
                    } else {
                        if (false !== ($line = 'ut_' . $val)) {
                            $val = $line;
                        }				
                        $temp['ut_' . $key] = $val;
                    }
                }
                $retval[] = $temp;
            }
            return $retval;
        }
        

        public function setTemplate($template)
        {
            $this->_template = $template;
        }
        
        public static function dump($val)
        {
            ob_start();
            print_r($val);
            $render = ob_get_contents();
            ob_end_clean();
            return $render;
        }

        public function _backtrace()
        {
            if (function_exists('debug_backtrace')) {
                $back = debug_backtrace();
                
                $file = (!isset($back['1']['file'])) ? '' : $back['1']['file'];
                $line = (!isset($back['1']['line'])) ? '' : $back['1']['line'];
                            
                return array('file' => $file, 'line' => $line);
            }
            return array('file' => 'Unknown', 'line' => 'Unknown');
        }

        public function _defaultTemplate()
        {	
            $this->_template = "\n".'<style>' . \WZ_Font::netto() . '</style><table style="font-family: netto, Trebuchet MS, verdana, tahoma, arial, serif; width: 80%; font-size: medium; margin: 10px 0; border-collapse: collapse; border: 1px solid #aaa; padding: 5px;">';
            $this->_template .= '{rows}';
            $this->_template .= "\n".'</table>';
            
            $this->_template_rows = "\n\t".'<tr>';
            $this->_template_rows .= "\n\t\t".'<th width="20%" style="background-color: #eee; text-align: left; border-bottom: 1px solid #aaa; border-right: 1px solid #aaa; padding: 5px;">{item}</th>';
            $this->_template_rows .= "\n\t\t".'<td style="border-bottom: 1px solid #aaa; padding: 5px;">{result}</td>';
            $this->_template_rows .= "\n\t".'</tr>';	
        }
        
        public function _parse_template()
        {
            if (!is_null($this->_template_rows)) {
                return;
            }
            
            if (is_null($this->_template)) {
                $this->_defaultTemplate();
                return;
            }
            
            if (!preg_match("/\{rows\}(.*?)\{\/rows\}/si", $this->_template, $match)) {
                $this->_defaultTemplate();
                return;
            }

            $this->_template_rows = $match['1'];
            $this->_template = str_replace($match['0'], '{rows}', $this->_template); 	
        }
        
    }
    
    function is_true($test)
    {
        return (is_bool($test) && $test === true) ? true : false;
    }
    
    function is_false($test)
    {
        return (is_bool($test) && $test === false) ? true : false;
    }
